package com.example.teachingSystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.teachingSystem.mapper.SysUserMapper;
import com.example.teachingSystem.pojo.entity.SysUser;
import com.example.teachingSystem.pojo.form.auth.*;
import com.example.teachingSystem.pojo.vo.LoginVo;
import com.example.teachingSystem.service.AuthService;
import com.example.teachingSystem.utils.JwtHelper;
import com.example.teachingSystem.utils.MD5Util;
import com.example.teachingSystem.utils.MailUtils;
import com.example.teachingSystem.utils.result.Result;
import com.example.teachingSystem.utils.result.ResultCodeEnum;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class AuthServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
        implements AuthService {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private JwtHelper jwtHelper;
    @Autowired
    private MailUtils mailUtils;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private HttpServletRequest request;

    private LambdaQueryWrapper<SysUser> queryWrapper;
    private static final String EMAIL_LOGIN_PRIM = "captcha:email:login:";
    private static final String EMAIL_CHANGE_PW_PRIM = "captcha:email:pw:";
    private static final String EMAIL_CHANGE_EM_OLD_PRIM = "captcha:email:em:old:";
    private static final String EMAIL_CHANGE_EM_NEW_PRIM = "captcha:email:em:new:";

    @Override
    public Result<LoginVo> userLogin(LoginForm loginForm) {
        //账号查询
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, loginForm.getUsername());
        SysUser loginUser = sysUserMapper.selectOne(queryWrapper);
        //账号判断
        if (loginUser == null) {
            return Result.build(null, ResultCodeEnum.USERNAME_ERROR);
        }
        //账号密码判断
        if (!StringUtils.isEmpty(loginForm.getPassword()) && loginUser.getPassword().equals(MD5Util.encrypt(loginForm.getPassword()))) {
            //账号密码正确
            //根据用户唯一标识生成token
            LoginVo loginVo = new LoginVo();
            loginVo.setToken(jwtHelper.createToken(loginUser.getId()));
            return Result.ok(loginVo);
        }
        //密码错误
        return Result.build(null, ResultCodeEnum.PASSWORD_ERROR);
    }

    @Override
    public Result<LoginVo> userLoginByEmail(EmailAndCaptchaForm emailAndCaptchaForm) {
        //账号查询
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getEmail, emailAndCaptchaForm.getEmail());
        SysUser loginUser = sysUserMapper.selectOne(queryWrapper);
        //账号判断
        if (loginUser == null) {
            return Result.build(null, ResultCodeEnum.LOGIN_EMAIL_ERROR);
        }
        String captcha = (String) redisTemplate.opsForValue().get(EMAIL_LOGIN_PRIM + emailAndCaptchaForm.getEmail());
        //账号密码判断
        if (captcha != null && !StringUtils.isEmpty(emailAndCaptchaForm.getCaptcha()) && captcha.equalsIgnoreCase(emailAndCaptchaForm.getCaptcha())) {
            //验证码正确
            //根据用户唯一标识生成token
            LoginVo loginVo = new LoginVo();
            loginVo.setToken(jwtHelper.createToken(loginUser.getId()));
            return Result.ok(loginVo);
        }
        //验证码错误
        return Result.build(null, ResultCodeEnum.CAPTCHA_ERROR);
    }

    @Override
    public Result<String> getLoginCaptcha(String email) {
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getEmail, email);
        if (!sysUserMapper.exists(queryWrapper)) {
            return Result.build(null, ResultCodeEnum.LOGIN_EMAIL_ERROR);
        }
        new Thread(() -> {
            String captcha = mailUtils.getCode();
            redisTemplate.opsForValue().set(EMAIL_LOGIN_PRIM + email, captcha, 5L, TimeUnit.MINUTES);
            mailUtils.sendMail(email, "您的登录验证码为：" + captcha + " 五分钟之内有效", "新闻发布管理平台验证码");
        }).start();
        return Result.ok("null", "邮件成功发送！");
    }

    @Override
    public Result<String> changeUserPassword(ChangePwdForm changePwdForm) {
        //账号查询
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, changePwdForm.getUsername());
        SysUser user = sysUserMapper.selectOne(queryWrapper);
        //账号判断
        if (user == null) {
            return Result.build(null, ResultCodeEnum.USERNAME_ERROR);
        }
        //账号密码判断
        if (!StringUtils.isEmpty(user.getPassword()) && user.getPassword().equals(MD5Util.encrypt(user.getPassword()))) {
            //账号密码正确
            // 使用 LambdaUpdateWrapper 修改指定属性
            LambdaUpdateWrapper<SysUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.eq(SysUser::getId, user.getId())
                    .set(SysUser::getPassword, MD5Util.encrypt(changePwdForm.getNewPassword()));
            this.update(lambdaUpdateWrapper); // 执行更新操作
            return Result.ok(null, "修改成功！");
        }
        //密码错误
        return Result.build(null, ResultCodeEnum.PASSWORD_ERROR);
    }

    @Override
    public Result<String> getChangePwdCaptcha(String email) {
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getEmail, email);
        if (!sysUserMapper.exists(queryWrapper)) {
            return Result.build(null, ResultCodeEnum.LOGIN_EMAIL_ERROR);
        }
        new Thread(() -> {
            String captcha = mailUtils.getCode();
            redisTemplate.opsForValue().set(EMAIL_CHANGE_PW_PRIM + email, captcha, 5L, TimeUnit.MINUTES);
            mailUtils.sendMail(email, "您的验证码为：" + captcha + " 五分钟之内有效", "新闻发布管理平台验证码");
        }).start();
        return Result.ok("null", "邮件成功发送！");
    }

    @Override
    public Result<String> changeUserPwdByEmail(ChangePwdByEmailForm changePwdByEmailForm) {
        //账号查询
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getEmail, changePwdByEmailForm.getEmail());
        SysUser user = sysUserMapper.selectOne(queryWrapper);
        //账号判断
        if (user == null) {
            return Result.build(null, ResultCodeEnum.LOGIN_EMAIL_ERROR);
        }

        String captcha = (String) redisTemplate.opsForValue().get(EMAIL_CHANGE_PW_PRIM + changePwdByEmailForm.getEmail());
        //判断
        if (captcha != null && !StringUtils.isEmpty(changePwdByEmailForm.getCaptcha()) && captcha.equalsIgnoreCase(changePwdByEmailForm.getCaptcha())) {
            //验证码正确
            // 使用 LambdaUpdateWrapper 修改指定属性
            LambdaUpdateWrapper<SysUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.eq(SysUser::getId, user.getId())
                    .set(SysUser::getPassword, MD5Util.encrypt(changePwdByEmailForm.getNewPassword()));
            this.update(lambdaUpdateWrapper); // 执行更新操作
            return Result.ok(null, "修改成功！");
        }
        //验证码错误
        return Result.build(null, ResultCodeEnum.CAPTCHA_ERROR);
    }

    @Override
    public Result<String> getOldEmailCaptcha(String email) {
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getEmail, email);
        if (!sysUserMapper.exists(queryWrapper)) {
            return Result.build(null, ResultCodeEnum.LOGIN_EMAIL_ERROR);
        }
        new Thread(() -> {
            String captcha = mailUtils.getCode();
            redisTemplate.opsForValue().set(EMAIL_CHANGE_EM_OLD_PRIM + email, captcha, 5L, TimeUnit.MINUTES);
            mailUtils.sendMail(email, "您的旧邮箱验证码为：" + captcha + " 五分钟之内有效", "新闻发布管理平台验证码");
        }).start();
        return Result.ok("null", "邮件成功发送！");
    }

    @Override
    public Result<String> verifyOldEmail(EmailAndCaptchaForm emailAndCaptchaForm) {
        String captcha = (String) redisTemplate.opsForValue().get(EMAIL_CHANGE_EM_OLD_PRIM + emailAndCaptchaForm.getEmail());
        //判断
        if (captcha != null && !StringUtils.isEmpty(emailAndCaptchaForm.getCaptcha()) && captcha.equalsIgnoreCase(emailAndCaptchaForm.getCaptcha())) {
            return Result.ok(null, "旧邮箱验证成功！");
        }
        //验证码错误
        return Result.build(null, ResultCodeEnum.CAPTCHA_ERROR);
    }

    @Override
    public Result<String> getNewEmailCaptcha(String email) {
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getEmail, email);
        if (sysUserMapper.exists(queryWrapper)) {
            return Result.build(null, ResultCodeEnum.EMAIL_USED);
        }
        new Thread(() -> {
            String captcha = mailUtils.getCode();
            redisTemplate.opsForValue().set(EMAIL_CHANGE_EM_NEW_PRIM + email, captcha, 5L, TimeUnit.MINUTES);
            mailUtils.sendMail(email, "您的新邮箱验证码为：" + captcha + " 五分钟之内有效", "新闻发布管理平台验证码");
        }).start();
        return Result.ok("null", "邮件成功发送！");
    }

    @Override
    public Result<String> verifyNewEmail(ChangeEmailForm changeEmailForm) {
        // 获取请求头中的令牌
        String token = request.getHeader("Authorization");
        if (token == null) {
            return Result.build(null, ResultCodeEnum.ILLEGAL_OPERATION);
        }
        Long userId = jwtHelper.getUserId(token);

        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getEmail, changeEmailForm.getEmail());
        SysUser user = this.getOne(queryWrapper);
        if (user == null || !userId.equals(user.getId())) {
            return Result.build(null, ResultCodeEnum.ILLEGAL_OPERATION);
        }

        String captcha = (String) redisTemplate.opsForValue().get(EMAIL_CHANGE_EM_NEW_PRIM + changeEmailForm.getNewEmail());
        //判断
        if (captcha != null && !StringUtils.isEmpty(changeEmailForm.getCaptcha()) && captcha.equalsIgnoreCase(changeEmailForm.getCaptcha())) {
            if (changeEmailForm.getEmail().equals(changeEmailForm.getNewEmail())) {
                return Result.build(null, 500, "当前的新旧邮箱相同");
            }

            LambdaUpdateWrapper<SysUser> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(SysUser::getId, userId)
                    .set(SysUser::getEmail, changeEmailForm.getNewEmail());
            this.update(updateWrapper);
            return Result.ok(null, "新邮箱修改成功！");
        }
        //验证码错误
        return Result.build(null, ResultCodeEnum.CAPTCHA_ERROR);
    }

}
